package com.daqian.chance.lbs.service;

import com.alibaba.fastjson.JSONObject;
import com.daqian.chance.lbs.dto.TencentAddressResult;
import com.daqian.chance.lbs.dto.TencentLocationResult;
import com.daqian.chance.lbs.dto.TencentSuggestionResult;
import com.daqian.chance.lbs.properties.LbsProperties;
import com.daqian.chance.lbs.util.RestTemplateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;

/**
 * 腾讯位置地理坐标位置服务
 * 官方api：https://lbs.qq.com/webservice_v1/guide-geocoder.html
 * @Author: daqian
 * @Date: 2020/4/8 10:23
 */
@Component
public class LBSTencentService {
    @Autowired
    private LbsProperties lbsProperties;

    /**
     * 腾讯位置服务接口URL
     */
    private final String TENCENT_LBS_URL_GEOCODER_LOCATION = "https://apis.map.qq.com/ws/geocoder/v1/";
    /**
     * 腾讯位置服务接口URL
     */
    private final String TENCENT_LBS_URL_GEOCODER_ADDRESS = "https://apis.map.qq.com/ws/geocoder/v1/";
    /**
     * 搜索提示
     */
    private final String TENCENT_LBS_URL_SUGGESTION = "https://apis.map.qq.com/ws/place/v1/suggestion";

    /**
     * 调用腾讯api
     * @param url    api url
     * @param params 参数
     * @param t      返回结果的实体类
     * @return
     */
    private <T> T invokeApi(String url, JSONObject params, Class<T> t) {
        return invokeApi(url, params, null, t);
    }

    /**
     * 调用腾讯api
     * @param url       api url
     * @param params    参数
     * @param resultKey 腾讯地图api响应结果字段的key（不同接口的返回格式不太一样。。真搞）
     * @param t         返回结果的实体类
     * @return
     */
    private <T> T invokeApi(String url, JSONObject params, String resultKey, Class<T> t) {
        // 默认key
        if (StringUtils.isEmpty(params.getString("key"))) {
            params.put("key", lbsProperties.getKey());
        }
        // 腾讯地图api响应结果字段的key
        resultKey = StringUtils.isEmpty(resultKey) ? "result" : resultKey;

        // 开始请求
        JSONObject result = JSONObject.parseObject(new RestTemplate().getForObject(RestTemplateUtil.buildUrlWithParam(url, params), String.class));
        if (result == null) {
            return null;
        }
        if (result.getInteger("status") != 0) {
            System.out.println(RestTemplateUtil.buildUrlWithParam(url, params));
            System.out.println(result.toJSONString());
            return null;
        }
        return result.getObject(resultKey, t);
    }

    /**
     * 腾讯地图-逆地址解析-坐标位置描述
     * 示例：{"status":0,"message":"query ok","request_id":"339e2dbc-f834-11e8-bf4a-6c92bf5bb237","result":{"location":{"lat":31.332012,"lng":121.49158},"address":"上海市宝山区长江南路3号","formatted_addresses":{"recommend":"长江南路地铁站","rough":"长江南路地铁站"},"address_component":{"nation":"中国","province":"上海市","city":"上海市","district":"宝山区","street":"长江南路","street_number":"长江南路3号"},"ad_info":{"nation_code":"156","adcode":"310113","city_code":"156310000","name":"中国,上海市,上海市,宝山区","location":{"lat":31.332012,"lng":121.491577},"nation":"中国","province":"上海市","city":"上海市","district":"宝山区"},"address_reference":{"crossroad":{"id":"6104676","title":"逸仙路/长江南路(路口)","location":{"lat":31.3311,"lng":121.491142},"_distance":104.1,"_dir_desc":"北"},"town":{"id":"310113113","title":"淞南镇","location":{"lat":31.332012,"lng":121.491577},"_distance":0,"_dir_desc":"内"},"street_number":{"id":"13159355764340638544","title":"长江南路3号","location":{"lat":31.331949,"lng":121.491409},"_distance":17.4,"_dir_desc":""},"street":{"id":"3841226627285285649","title":"逸仙路","location":{"lat":31.331884,"lng":121.491745},"_distance":15.9,"_dir_desc":"西"},"landmark_l2":{"id":"10804000183069644061","title":"长江南路地铁站","location":{"lat":31.331793,"lng":121.491425},"_distance":0,"_dir_desc":"内"}}}}
     * @param longitude 经度
     * @param latitude  纬度
     * @return
     */
    public TencentLocationResult location(BigDecimal longitude, BigDecimal latitude) {
        if (longitude == null || latitude == null) {
            return null;
        }
        JSONObject params = new JSONObject(2);
        params.put("location", latitude + "," + longitude);
        return invokeApi(TENCENT_LBS_URL_GEOCODER_LOCATION, params, TencentLocationResult.class);
    }

    /**
     * 腾讯地图-地址解析-地址转坐标
     * 示例：{"title":"海淀区","location":{"lng":116.29845,"lat":39.95933},"ad_info":{"adcode":"110108"},"address_components":{"province":"北京市","city":"北京市","district":"海淀区","street":"","street_number":""},"similarity":0.8,"deviation":1000,"reliability":1,"level":2}
     * @param address 详细地址，如北京市海淀区彩和坊路海淀西大街74号
     * @return
     */
    public TencentAddressResult address(String address) {
        if (StringUtils.isEmpty(address)) {
            return null;
        }
        JSONObject params = new JSONObject(2);
        params.put("address", address.trim());
        return invokeApi(TENCENT_LBS_URL_GEOCODER_ADDRESS, params, TencentAddressResult.class);
    }

    /**
     * 腾讯地图-关键词输入提示
     * 示例：{"title":"海淀区","location":{"lng":116.29845,"lat":39.95933},"ad_info":{"adcode":"110108"},"address_components":{"province":"北京市","city":"北京市","district":"海淀区","street":"","street_number":""},"similarity":0.8,"deviation":1000,"reliability":1,"level":2}
     * @param keyword 详细地址，如海淀西大街
     * @param region  限制范围，如广州，则只在广州内提示
     * @return
     */
    public TencentSuggestionResult[] suggestion(String keyword, String region) {
        if (StringUtils.isEmpty(keyword)) {
            return null;
        }
        JSONObject params = new JSONObject(2);
        params.put("keyword", keyword.trim());
        params.put("region", region);
        return invokeApi(TENCENT_LBS_URL_SUGGESTION, params, "data", TencentSuggestionResult[].class);
    }

}
